#include <stdlib.h>
#include <string.h>
+
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
GdkWindow *prev_window;
gboolean button1_pressed, button2_pressed, button3_pressed;
gboolean click_grab;
-} PS2Mouse;
+
+ guchar fidmour_bytes[5];
+ int fidmour_nbytes;
+} MouseDevice;
typedef struct {
gint fd, fd_tag, consfd;
static Keyboard * tty_keyboard_open(void);
static guint keyboard_get_state(Keyboard *k);
-PS2Mouse *gdk_fb_ps2mouse = NULL;
+static MouseDevice *gdk_fb_mouse = NULL;
static Keyboard *keyboard = NULL;
-FILE *debug_out;
static guint multiclick_tag;
static GdkEvent *multiclick_event = NULL;
}
static void
-send_button_event(PS2Mouse *mouse, guint button, gboolean press_event, time_t the_time)
+send_button_event(MouseDevice *mouse, guint button, gboolean press_event, time_t the_time)
{
GdkEvent *event;
gint x, y;
}
static void
-move_pointer(PS2Mouse *mouse, GdkWindow *in_window)
+move_pointer(MouseDevice *mouse, GdkWindow *in_window)
{
GdkCursor *the_cursor;
{
GdkWindow *win = gdk_window_get_pointer(NULL, NULL, NULL, NULL);
- move_pointer(gdk_fb_ps2mouse, win);
+ move_pointer(gdk_fb_mouse, win);
}
void gdk_fb_window_visibility_crossing(GdkWindow *window, gboolean is_show, gboolean is_grab)
event->crossing.state = my_mask;
}
- if(gdk_fb_ps2mouse->prev_window)
- gdk_window_unref(gdk_fb_ps2mouse->prev_window);
- gdk_fb_ps2mouse->prev_window = gdk_window_ref(newwin);
+ if(gdk_fb_mouse->prev_window)
+ gdk_window_unref(gdk_fb_mouse->prev_window);
+ gdk_fb_mouse->prev_window = gdk_window_ref(newwin);
+ }
+}
+
+static void
+handle_mouse_input(MouseDevice *mouse, gboolean got_motion)
+{
+ GdkWindow *mousewin;
+ GdkEvent *event;
+ gint x, y;
+ GdkWindow *win;
+ guint state;
+
+ if(_gdk_fb_pointer_grab_confine)
+ mousewin = _gdk_fb_pointer_grab_confine;
+ else
+ mousewin = gdk_parent_root;
+
+ if(mouse->x < GDK_DRAWABLE_IMPL_FBDATA(mousewin)->llim_x)
+ mouse->x = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->llim_x;
+ else if(mouse->x > (GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_x - 1))
+ mouse->x = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_x - 1;
+ if(mouse->y < GDK_DRAWABLE_IMPL_FBDATA(mousewin)->llim_y)
+ mouse->y = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->llim_y;
+ else if(mouse->y > (GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_y - 1))
+ mouse->y = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_y - 1;
+
+ if(!got_motion)
+ return;
+
+ win = gdk_window_get_pointer(NULL, NULL, NULL, NULL);
+ move_pointer(mouse, win);
+ if(_gdk_fb_pointer_grab_window_events)
+ win = _gdk_fb_pointer_grab_window_events;
+
+ gdk_window_get_origin(win, &x, &y);
+ x = mouse->x - x;
+ y = mouse->y - y;
+
+
+ state = (mouse->button1_pressed?GDK_BUTTON1_MASK:0)
+ | (mouse->button2_pressed?GDK_BUTTON2_MASK:0)
+ | (mouse->button3_pressed?GDK_BUTTON3_MASK:0)
+ | keyboard_get_state(keyboard);
+
+ event = gdk_event_make (win, GDK_MOTION_NOTIFY, TRUE);
+ if(event)
+ {
+ event->motion.x = x;
+ event->motion.y = y;
+ event->motion.state = state;
+ event->motion.is_hint = FALSE;
+ event->motion.device = gdk_core_pointer;
+ event->motion.x_root = mouse->x;
+ event->motion.y_root = mouse->y;
+ }
+
+ if(win != mouse->prev_window)
+ {
+ GdkEvent *evel;
+
+ if(mouse->prev_window && (evel = gdk_event_make(mouse->prev_window, GDK_LEAVE_NOTIFY, TRUE)))
+ {
+ evel->crossing.subwindow = gdk_window_ref(win);
+ evel->crossing.x = x;
+ evel->crossing.y = y;
+ evel->crossing.x_root = mouse->x;
+ evel->crossing.y_root = mouse->y;
+ evel->crossing.mode = GDK_CROSSING_NORMAL;
+ evel->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ evel->crossing.focus = FALSE;
+ evel->crossing.state = state;
+ }
+
+ evel = gdk_event_make(win, GDK_ENTER_NOTIFY, TRUE);
+ if(evel)
+ {
+ evel->crossing.subwindow = gdk_window_ref(mouse->prev_window?mouse->prev_window:gdk_parent_root);
+ evel->crossing.x = x;
+ evel->crossing.y = y;
+ evel->crossing.x_root = mouse->x;
+ evel->crossing.y_root = mouse->y;
+ evel->crossing.mode = GDK_CROSSING_NORMAL;
+ evel->crossing.detail = GDK_NOTIFY_UNKNOWN;
+ evel->crossing.focus = FALSE;
+ evel->crossing.state = state;
+ }
+
+ if(mouse->prev_window)
+ gdk_window_unref(mouse->prev_window);
+ mouse->prev_window = gdk_window_ref(win);
+ }
+}
+
+static gboolean
+pull_fidmour_packet(MouseDevice *mouse, gboolean *btn_down, int *x, int *y)
+{
+ gboolean keep_reading = TRUE;
+
+ while(keep_reading)
+ {
+ int n;
+
+ n = read(mouse->fd, mouse->fidmour_bytes + mouse->fidmour_nbytes, 5 - mouse->fidmour_nbytes);
+ if(n < 0)
+ return FALSE;
+ else if(n == 0)
+ {
+ g_error("EOF on mouse device!");
+ g_source_remove(mouse->fd_tag);
+ return FALSE;
+ }
+
+ mouse->fidmour_nbytes += n;
+
+ n = 0;
+ if(!(mouse->fidmour_bytes[0] & 0x80))
+ {
+ int i;
+ /* We haven't received any of the packet yet but there is no header at the beginning */
+ for(i = 1; i < mouse->fidmour_nbytes; i++)
+ {
+ if(mouse->fidmour_bytes[i] & 0x80)
+ {
+ n = i;
+ break;
+ }
+ }
+ }
+ else if(mouse->fidmour_nbytes > 1
+ && ((mouse->fidmour_bytes[0] & 0x90) == 0x90))
+ {
+ /* eat the 0x90 and following byte, no clue what it's for */
+ n = 2;
+ }
+ else if(mouse->fidmour_nbytes == 5)
+ {
+ switch(mouse->fidmour_bytes[0] & 0x80)
+ {
+ case 2:
+ *btn_down = 0;
+ break;
+ case 1:
+ case 0:
+ *btn_down = 1;
+ break;
+ }
+ *x = (mouse->fidmour_bytes[1] << 1) + (mouse->fidmour_bytes[2] << 7);
+ *y = (mouse->fidmour_bytes[3] << 1) + (mouse->fidmour_bytes[4] << 7);
+ n = 5;
+ keep_reading = FALSE;
+ }
+
+ if(n)
+ {
+ memmove(mouse->fidmour_bytes, mouse->fidmour_bytes+n, mouse->fidmour_nbytes-n);
+ mouse->fidmour_nbytes -= n;
+ }
}
+
+ return TRUE;
}
static gboolean
-handle_input(GIOChannel *gioc, GIOCondition cond, gpointer data)
+handle_input_fidmour(GIOChannel *gioc, GIOCondition cond, gpointer data)
{
+ MouseDevice *mouse = data;
+ int x, y;
+ gboolean got_motion = FALSE;
+ gboolean btn_down;
+ time_t the_time;
+ GTimeVal tv;
+
+ g_get_current_time(&tv);
+ the_time = tv.tv_sec;
+
+ while(pull_fidmour_packet(mouse, &btn_down, &x, &y))
+ {
+#if 0
+ if(x != mouse->x
+ || y != mouse->y)
+ got_motion = TRUE;
+ mouse->x = x;
+ mouse->y = y;
+#else
+ g_print("%d at %dx%d\n",
+ btn_down, x, y);
+ continue;
+#endif
+
+
+ if(btn_down != mouse->button1_pressed)
+ {
+ if(got_motion)
+ {
+ handle_mouse_input(mouse, TRUE);
+ got_motion = FALSE;
+ }
+
+ mouse->button1_pressed = btn_down;
+ send_button_event(mouse, 1, btn_down, the_time);
+ }
+ }
+
+ if(got_motion)
+ handle_mouse_input(mouse, TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+handle_input_ps2(GIOChannel *gioc, GIOCondition cond, gpointer data)
+{
+ MouseDevice *mouse = data;
guchar buf[3];
int n, left, dx=0, dy=0;
- PS2Mouse *mouse = data;
gboolean new_button1, new_button2, new_button3;
time_t the_time;
GTimeVal curtime;
- GdkWindow *mousewin;
gboolean got_motion = FALSE;
g_get_current_time(&curtime);
new_button3 = (buf[0] & 2) && 1;
new_button2 = (buf[0] & 4) && 1;
+ if(got_motion &&
+ (new_button1 != mouse->button1_pressed
+ || new_button2 != mouse->button2_pressed
+ || new_button3 != mouse->button3_pressed))
+ {
+ /* If a mouse button state changes we need to get correct ordering with enter/leave events,
+ so push those out via handle_mouse_input */
+ got_motion = FALSE;
+ handle_mouse_input(mouse, TRUE);
+ }
+
if(new_button1 != mouse->button1_pressed)
{
mouse->button1_pressed = new_button1;
if(dx || dy)
got_motion = TRUE;
}
- done_reading_mouse_events:
-
- if(_gdk_fb_pointer_grab_confine)
- mousewin = _gdk_fb_pointer_grab_confine;
- else
- mousewin = gdk_parent_root;
-
- if(mouse->x < 0)
- mouse->x = 0;
- else if(mouse->x > (GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_x - 1))
- mouse->x = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_x - 1;
- if(mouse->y < 0)
- mouse->y = 0;
- else if(mouse->y > (GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_y - 1))
- mouse->y = GDK_DRAWABLE_IMPL_FBDATA(mousewin)->lim_y - 1;
- if(got_motion) {
- GdkEvent *event;
- gint x, y;
- GdkWindow *win;
- guint state;
-
- win = gdk_window_get_pointer(NULL, NULL, NULL, NULL);
- move_pointer(mouse, win);
- if(_gdk_fb_pointer_grab_window_events)
- win = _gdk_fb_pointer_grab_window_events;
-
- gdk_window_get_origin(win, &x, &y);
- x = mouse->x - x;
- y = mouse->y - y;
-
-
- state = (mouse->button1_pressed?GDK_BUTTON1_MASK:0)
- | (mouse->button2_pressed?GDK_BUTTON2_MASK:0)
- | (mouse->button3_pressed?GDK_BUTTON3_MASK:0)
- | keyboard_get_state(keyboard);
-
- event = gdk_event_make (win, GDK_MOTION_NOTIFY, TRUE);
- if(event)
- {
- event->motion.x = x;
- event->motion.y = y;
- event->motion.state = state;
- event->motion.is_hint = FALSE;
- event->motion.device = gdk_core_pointer;
- event->motion.x_root = mouse->x;
- event->motion.y_root = mouse->y;
- }
-
- if(win != mouse->prev_window)
- {
- GdkEvent *evel;
-
- if(mouse->prev_window && (evel = gdk_event_make(mouse->prev_window, GDK_LEAVE_NOTIFY, TRUE)))
- {
- evel->crossing.subwindow = gdk_window_ref(win);
- evel->crossing.x = x;
- evel->crossing.y = y;
- evel->crossing.x_root = mouse->x;
- evel->crossing.y_root = mouse->y;
- evel->crossing.mode = GDK_CROSSING_NORMAL;
- evel->crossing.detail = GDK_NOTIFY_UNKNOWN;
- evel->crossing.focus = FALSE;
- evel->crossing.state = state;
- }
-
- evel = gdk_event_make(win, GDK_ENTER_NOTIFY, TRUE);
- if(evel)
- {
- evel->crossing.subwindow = gdk_window_ref(mouse->prev_window?mouse->prev_window:gdk_parent_root);
- evel->crossing.x = x;
- evel->crossing.y = y;
- evel->crossing.x_root = mouse->x;
- evel->crossing.y_root = mouse->y;
- evel->crossing.mode = GDK_CROSSING_NORMAL;
- evel->crossing.detail = GDK_NOTIFY_UNKNOWN;
- evel->crossing.focus = FALSE;
- evel->crossing.state = state;
- }
-
- if(mouse->prev_window)
- gdk_window_unref(mouse->prev_window);
- mouse->prev_window = gdk_window_ref(win);
- }
- }
+ done_reading_mouse_events:
+ if(got_motion)
+ handle_mouse_input(mouse, TRUE);
return TRUE;
}
-static PS2Mouse *
+static MouseDevice *
mouse_open(void)
{
- PS2Mouse *retval = g_new0(PS2Mouse, 1);
+ MouseDevice *retval = g_new0(MouseDevice, 1);
guchar buf[7];
int i = 0;
GIOChannel *gioc;
-
- retval->fd = open("/dev/psaux", O_RDWR);
- if(retval->fd < 0)
+ char *mousedev, *ctmp;
+ int mode;
+ enum { PS2_MOUSE, FIDMOUR_MOUSE, UNKNOWN_MOUSE } type;
+
+ retval->fd = -1;
+ mode = O_RDWR;
+ ctmp = getenv("GDK_MOUSETYPE");
+ if(ctmp)
{
- g_free(retval);
- return NULL;
+ if(!strcmp(ctmp, "fidmour"))
+ type = FIDMOUR_MOUSE;
+ else if(!strcmp(ctmp, "ps2"))
+ type = PS2_MOUSE;
+ else
+ {
+ g_print("Unknown mouse type %s\n", ctmp);
+ type = UNKNOWN_MOUSE;
+ }
}
+ else
+ type = PS2_MOUSE;
- /* From xf86_Mouse.c */
- buf[i++] = 230; /* 1:1 scaling */
- buf[i++] = 244; /* enable mouse */
- buf[i++] = 243; /* Sample rate */
- buf[i++] = 200;
- buf[i++] = 232; /* device resolution */
- buf[i++] = 1;
- write(retval->fd, buf, i);
- if(read(retval->fd, buf, 3) < 0
- || getenv("GDK_NO_PS2MOUSE")) /* Get rid of misc garbage whatever stuff from mouse */
+ switch(type)
{
- close(retval->fd);
- retval->fd = -1;
+ case PS2_MOUSE:
+ mousedev = "/dev/psaux";
+ mode = O_RDWR;
+ break;
+ case FIDMOUR_MOUSE:
+ mousedev = "/dev/fidmour";
+ mode = O_RDONLY;
+ break;
+ default:
+ goto error;
+ break;
}
- else
+
+ ctmp = getenv("GDK_MOUSEDEV");
+ if(ctmp)
+ mousedev = ctmp;
+
+ retval->fd = open(mousedev, mode);
+ if(retval->fd < 0)
+ goto error;
+
+ switch(type)
{
+ case PS2_MOUSE:
+ /* From xf86_Mouse.c */
+ buf[i++] = 230; /* 1:1 scaling */
+ buf[i++] = 244; /* enable mouse */
+ buf[i++] = 243; /* Sample rate */
+ buf[i++] = 200;
+ buf[i++] = 232; /* device resolution */
+ buf[i++] = 1;
+ write(retval->fd, buf, i);
+ if(read(retval->fd, buf, 3) < 0)
+ goto error;
fcntl(retval->fd, F_SETFL, O_RDWR|O_NONBLOCK);
gioc = g_io_channel_unix_new(retval->fd);
- retval->fd_tag = g_io_add_watch(gioc, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_input, retval);
+ retval->fd_tag = g_io_add_watch(gioc, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_input_ps2, retval);
+ break;
+
+ case FIDMOUR_MOUSE:
+ gioc = g_io_channel_unix_new(retval->fd);
+ retval->fd_tag = g_io_add_watch(gioc, G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, handle_input_fidmour, retval);
+ break;
+ default:
+ g_assert_not_reached();
+ break;
}
retval->x = gdk_display->modeinfo.xres >> 1;
retval->y = gdk_display->modeinfo.yres >> 1;
return retval;
+
+ error:
+ /* No errors allowed once fd_tag is added */
+ if(retval->fd >= 0)
+ close(retval->fd);
+ g_free(retval);
+ return NULL;
}
void
gdk_input_ignore_core = FALSE;
- gdk_fb_ps2mouse = mouse_open();
+ gdk_fb_mouse = mouse_open();
}
void
gdk_input_ps2_get_mouseinfo(gint *x, gint *y, GdkModifierType *mask)
{
- *x = gdk_fb_ps2mouse->x;
- *y = gdk_fb_ps2mouse->y;
+ *x = gdk_fb_mouse->x;
+ *y = gdk_fb_mouse->y;
*mask =
- (gdk_fb_ps2mouse->button1_pressed?GDK_BUTTON1_MASK:0)
- | (gdk_fb_ps2mouse->button2_pressed?GDK_BUTTON2_MASK:0)
- | (gdk_fb_ps2mouse->button3_pressed?GDK_BUTTON3_MASK:0)
+ (gdk_fb_mouse->button1_pressed?GDK_BUTTON1_MASK:0)
+ | (gdk_fb_mouse->button2_pressed?GDK_BUTTON2_MASK:0)
+ | (gdk_fb_mouse->button3_pressed?GDK_BUTTON3_MASK:0)
| keyboard_get_state(keyboard);
}
{
gint vtnum = trans_table[base_char][0] - GDK_F1 + 1;
- fprintf(debug_out, "Switching VTs\n");
-
/* Do the whole funky VT switch thing */
ioctl(k->consfd, VT_ACTIVATE, vtnum);
ioctl(k->consfd, VT_WAITACTIVE, k->vtnum);
ioctl(retval->consfd, VT_ACTIVATE, retval->vtnum);
ioctl(retval->consfd, VT_WAITACTIVE, retval->vtnum);
- debug_out = fdopen(dup(2), "w");
-
#if 0
close(0);
close(1);